package com.ecloud.gardensterminal.server.scheduling;

import com.ecloud.gardensterminal.constant.DeviceTypeConstant;
import com.ecloud.gardensterminal.domain.*;
import com.ecloud.gardensterminal.server.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.List;

/**
 * @author Squbi
 */
@Component
public class AutoControlSchedulingService {
    private final Logger logger = LoggerFactory.getLogger(AutoControlSchedulingService.class);

    @Autowired
    private GardensThresholdService gardensThresholdService;

    @Autowired
    private GardensWeatherService weatherService;

    @Autowired
    private GardensSoilService soilService;

    @Autowired
    private GardensSleetService sleetService;

    @Autowired
    private GardensDeviceService gardensDeviceService;

    @Autowired
    private MqttService mqttService;

    private List<GardensWeather> gardensWeathers;

    private List<GardensSoil> gardensSoils;

    private List<GardensSleet> gardensSleets;

    private List<GardensThreshold> thresholds;

    private void refresh() {
        gardensWeathers = weatherService.selectNewly();
        gardensSoils = soilService.selectNewly();
        gardensSleets = sleetService.selectNewly();
        thresholds = gardensThresholdService.getThresholds();

    }

    private GardensWeather findWeather(Integer deviceId) {
        if (gardensWeathers == null) {
            return null;
        }
        for (GardensWeather gardensWeather : gardensWeathers) {
            if (gardensWeather.getDeviceId().equals(deviceId)) {
                return gardensWeather;
            }
        }
        return null;
    }

    private GardensSoil findSoils(Integer deviceId) {
        if (gardensSoils == null) {
            return null;
        }
        for (GardensSoil gardensSoil : gardensSoils) {
            if (gardensSoil.getDeviceId().equals(deviceId)) {
                return gardensSoil;
            }
        }
        return null;
    }

    private GardensSleet findSleet(Integer deviceId) {
        if (gardensSleets == null) {
            return null;
        }
        for (GardensSleet gardensSleet : gardensSleets) {
            if (gardensSleet.getDeviceId().equals(deviceId)) {
                return gardensSleet;
            }
        }
        return null;
    }

    private boolean inThreshold(GardensThreshold gardensThreshold, Class<?> aClass, Object o) {
        try {
            Field declaredField = aClass.getDeclaredField(gardensThreshold.getThresholdField());
            declaredField.setAccessible(true);
            if (aClass != GardensSleet.class) {
                Double d = (Double) declaredField.get(o);
                if (gardensThreshold.getThresholdMin() < d && d < gardensThreshold.getThresholdMax()) {
                    return true;
                }
            } else {
                Boolean b = (Boolean) declaredField.get(o);
                if (gardensThreshold.getThresholdMin() == 1 && b) {
                    return true;
                }
            }
        } catch (Exception e) {
            logger.error("err in threshold auto running", e);
        }
        return false;
    }

    /**
     * 判断值是否到达阈值以执行
     *
     * @param gardensThreshold {@link GardensThreshold} 阈值
     * @return Boolean
     * @author Squbi
     * @date 2022/2/17 10:30
     */
    private boolean needExec(GardensThreshold gardensThreshold) {
        GardensDevice gardensDevice = gardensDeviceService.selectById(gardensThreshold.getDeviceId());
        if (gardensDevice == null) {
            return false;
        }
        if (gardensDevice.getDeviceType() == DeviceTypeConstant.WEATHER) {
            GardensWeather weather = findWeather(gardensDevice.getDeviceId());
            if (weather == null) {
                return false;
            }
            return inThreshold(gardensThreshold, GardensWeather.class, weather);
        } else if (gardensDevice.getDeviceType() == DeviceTypeConstant.SOIL) {
            GardensSoil soils = findSoils(gardensDevice.getDeviceId());
            if (soils == null) {
                return false;
            }
            return inThreshold(gardensThreshold, GardensSoil.class, soils);
        } else if (gardensDevice.getDeviceType() == DeviceTypeConstant.SLEET) {
            GardensSleet sleet = findSleet(gardensDevice.getDeviceId());
            if (sleet == null) {
                return false;
            }
            return inThreshold(gardensThreshold, GardensSleet.class, sleet);
        }
        return false;
    }

    @Scheduled(cron = "0 0/1 * * * ?")
    public void execute() {
        refresh();
        for (GardensThreshold threshold : thresholds) {
            if (needExec(threshold)) {
                logger.info("{} to exec", threshold.getThresholdId());
                mqttService.sendSwitch(threshold.getCallDeviceId(), threshold.getCallOperation());
            }
        }
    }
}
